import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:provider/provider.dart';
import 'package:string_validator/string_validator.dart';
import 'package:webview_flutter/webview_flutter.dart';

import '../../common/channel/action.dart';
import '../../common/config.dart';
import '../../common/utils/tracker.dart';

class WebScreen extends StatefulWidget {
  final String url;
  final bool closable;

  const WebScreen({super.key, required this.url, this.closable = true});

  @override
  State<WebScreen> createState() => _WebScreenState();
}

class _WebScreenState extends State<WebScreen> {
  final String title = Config.appName;

  late final WebViewController controller;

  final _WebIndex index = _WebIndex();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.white,
      appBar: AppBar(
        automaticallyImplyLeading: widget.closable,
        leading: widget.closable
            ? GestureDetector(
                onTap: () async {
                  if (await controller.canGoBack()) {
                    await controller.goBack();
                  } else {
                    if (!context.mounted) return;
                    context.pop();
                  }
                },
                child: const Padding(
                  padding: EdgeInsets.all(16),
                  child: Icon(Icons.arrow_back_ios, color: Colors.white),
                ),
              )
            : null,
        title: Padding(
          padding: widget.closable
              ? EdgeInsets.zero
              : const EdgeInsets.symmetric(horizontal: 16),
          child: Text(title, style: const TextStyle(fontSize: 18)),
        ),
        backgroundColor: const Color(0xff4744d3),
      ),
      body: ChangeNotifierProvider.value(
        value: index,
        builder: (context, child) {
          double progress = context.watch<_WebIndex>().value / 100.0;
          return Stack(
            children: [
              WebViewWidget(controller: controller),
              Visibility(
                visible: progress < 1,
                child: SizedBox(
                  height: 1,
                  child: LinearProgressIndicator(
                    backgroundColor: Colors.white,
                    valueColor: const AlwaysStoppedAnimation(Color(0xff4744d3)),
                    value: progress,
                  ),
                ),
              ),
            ],
          );
        },
      ),
    );
  }

  @override
  void initState() {
    super.initState();
    // #docregion webview_controller
    controller = WebViewController()
      ..enableZoom(false)
      ..setJavaScriptMode(JavaScriptMode.unrestricted)
      ..setBackgroundColor(const Color(0x00000000))
      ..setNavigationDelegate(
        NavigationDelegate(
          onProgress: (int progress) {
            // Update loading bar.
            index.go(progress);
          },
          onPageStarted: (String url) {},
          onPageFinished: (String url) {},
          onWebResourceError: (WebResourceError error) {},
          onNavigationRequest: (NavigationRequest request) async {
            final String url = request.url;
            return await handleRequest(url);
          },
        ),
      );
    if (isURL(widget.url)) {
      controller.loadRequest(Uri.parse(widget.url));
    } else if (widget.url.startsWith('assets/')) {
      controller.loadFlutterAsset(widget.url);
    } else {
      controller.loadHtmlString(widget.url);
    }
  }

  Future<NavigationDecision> handleRequest(String url) async {
    final bool isHttpUrl = isURL(url);
    if (isHttpUrl) {
      return NavigationDecision.navigate;
    }
    LaunchResult result = await action.launch(url);
    switch (result) {
      case LaunchResult.complete:
        Tracker.trackJumpComplete();
        break;
      case LaunchResult.notFound:
        Tracker.trackJumpNotFound();
        break;
      case LaunchResult.error:
        Tracker.trackJumpError();
        break;
    }
    return NavigationDecision.prevent;
  }
}

class _WebIndex extends ChangeNotifier {
  int _value = 0;

  int get value => _value;

  void go(int value) {
    _value = value;
    notifyListeners();
  }
}
